# pk/WindowManager.py
import win32gui
import win32api
import win32con
import win32ui
import cv2
import numpy as np
import random
import time
import os
import sys


# 资源路径处理
def resource_path(relative_path):
    """ 获取打包后的资源绝对路径 """
    if getattr(sys, 'frozen', False):
        base_path = sys._MEIPASS
    else:
        base_path = os.path.abspath(".")
    return os.path.join(base_path, relative_path)


# 窗口操作模块
class WindowManager:
    @staticmethod
    def get_window_handle_by_title(window_title):
        return win32gui.FindWindow(None, window_title)

    @staticmethod
    def click_in_window(hwnd, x, y, click_type='left'):
        lParam = win32api.MAKELONG(x, y)
        msg_down = win32con.WM_LBUTTONDOWN if click_type == 'left' else win32con.WM_RBUTTONDOWN
        msg_up = win32con.WM_LBUTTONUP if click_type == 'left' else win32con.WM_RBUTTONUP
        win32gui.PostMessage(hwnd, msg_down, 0, lParam)
        win32gui.PostMessage(hwnd, msg_up, 0, lParam)

    @staticmethod
    def capture_window(hwnd):
        """截取指定窗口句柄的图像并转为OpenCV格式"""
        left, top, right, bottom = win32gui.GetClientRect(hwnd)
        width = right - left
        height = bottom - top

        hwnd_dc = win32gui.GetWindowDC(hwnd)
        mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
        save_dc = mfc_dc.CreateCompatibleDC()
        bitmap = win32ui.CreateBitmap()
        bitmap.CreateCompatibleBitmap(mfc_dc, width, height)
        save_dc.SelectObject(bitmap)
        save_dc.BitBlt((0, 0), (width, height), mfc_dc, (0, 0), win32con.SRCCOPY)

        img_data = bitmap.GetBitmapBits(True)
        img = np.frombuffer(img_data, dtype=np.uint8).reshape((height, width, 4))
        img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)

        win32gui.DeleteObject(bitmap.GetHandle())
        save_dc.DeleteDC()
        mfc_dc.DeleteDC()
        win32gui.ReleaseDC(hwnd, hwnd_dc)
        return img

    @staticmethod
    def get_window_rect():
        """获取当前窗口的屏幕坐标"""
        hwnd = win32gui.GetForegroundWindow()
        return win32gui.GetWindowRect(hwnd)

    @staticmethod
    def get_window_info(hwnd):
        """获取窗口详细信息"""
        if win32gui.IsWindowVisible(hwnd):
            title = win32gui.GetWindowText(hwnd)
            return hwnd, title[:30],"人族", "自行备注用于区分是那个角色"
        return None

    @staticmethod
    def set_window_size(hwnd, x, y, width, height):
        try:
            # 确保hwnd是整数类型的窗口句柄
            if isinstance(hwnd, str):
                try:
                    hwnd = int(hwnd)
                except ValueError:
                    print(f"错误: 无效的窗口句柄 '{hwnd}'，必须是整数")
                    return

            # 检查窗口句柄是否有效
            if not win32gui.IsWindow(hwnd):
                print(f"错误: 窗口句柄 {hwnd} 无效")
                return

            # 尝试多种方式显示窗口，确保窗口能够显示出来
            # 1. 先尝试恢复窗口（如果是最小化状态）
            win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
            time.sleep(0.05)
            # 验证窗口是否成功显示
            if win32gui.IsWindowVisible(hwnd):
                print(f"成功: 窗口 {hwnd} 已显示并调整大小")
            else:
                print(f"警告: 窗口 {hwnd} 可能未能正确显示")

        except Exception as e:
            print(f"设置窗口大小和位置时出错: {str(e)}")

    @staticmethod
    def find_template_in_window(hwnd, template_path, threshold=0.8):
        """改进版：返回区域内随机坐标点"""
        # 修改为资源路径
        resolved_path = resource_path(template_path)
        template = cv2.imread(resolved_path, cv2.IMREAD_GRAYSCALE)
        w, h = template.shape[::-1]  # 获取模板尺寸

        window_img = WindowManager.captureWindow(hwnd)
        window_gray = cv2.cvtColor(window_img, cv2.COLOR_BGR2GRAY)

        # 模板匹配
        res = cv2.matchTemplate(window_gray, template, cv2.TM_CCOEFF_NORMED)
        loc = np.where(res >= threshold)

        # 生成随机坐标点
        random_points = []
        for pt in zip(*loc[::-1]):  # 遍历每个匹配位置
            x1, y1 = pt[0], pt[1]
            x2 = x1 + w
            y2 = y1 + h

            # 在匹配区域内生成随机坐标
            rand_x = random.randint(x1, x2)
            rand_y = random.randint(y1, y2)
            random_points.append(rand_x)
            random_points.append(rand_y)
        return random_points

    @staticmethod
    def sleep(custom_time):
        """最低0.1秒防止误操作"""
        if custom_time is None:
            custom_time = 1
        # 确保最小休眠时间为0.1秒
        min_time = 0.1
        if custom_time > 1:
            """随机休眠1到3秒"""
            sleep_time = random.uniform(1, 3)
            time.sleep(sleep_time)
        else:
            """随机休眠0到传入值之间的时间（但不低于0.1秒）"""
            # 取传入值和最小时间的最大值作为上限，确保不会低于0.1秒
            max_sleep = max(custom_time, min_time)
            sleep_time = random.uniform(0, max_sleep)
            time.sleep(sleep_time)

    @staticmethod
    def findImgAndClick(hwnd, template_path, threshold=0.8):
        try:
            # client_left, client_top = win32gui.ClientToScreen(hwnd, (0, 0))
            # print(client_left, client_top)
            dengluyouxi = WindowManager.find_template_in_window(hwnd, template_path, threshold)
            if dengluyouxi:
                print("找到图片", template_path)
                print("找到图片坐标", dengluyouxi[0] - 8,dengluyouxi[1] - 31)
                WindowManager.click_in_window(hwnd, dengluyouxi[0] - 8, dengluyouxi[1] - 31)
                WindowManager.sleep(1)
                return True
            else:
                print("未找到", template_path)
                return False
        except Exception as e:
            print(f"发生错误: {str(e)}")

    @staticmethod
    def findImgAndDubleClick(hwnd, template_path, threshold=0.8):
        try:
            client_left, client_top = win32gui.ClientToScreen(hwnd, (0, 0))
            print(client_left, client_top)
            dengluyouxi = WindowManager.find_template_in_window(hwnd, template_path, threshold)
            if dengluyouxi:
                print("找到图片", template_path)
                WindowManager.click_in_window(hwnd, dengluyouxi[0] - 8, dengluyouxi[1] - 31)
                WindowManager.click_in_window(hwnd, dengluyouxi[0] - 8, dengluyouxi[1] - 31)
                WindowManager.sleep(1)
                return True
            else:
                print("未找到", template_path)
                return False
        except Exception as e:
            print(f"发生错误: {str(e)}")

    @staticmethod
    def findImg(hwnd, template_path, threshold=0.8):
        try:
            client_left, client_top = win32gui.ClientToScreen(hwnd, (0, 0))
            print(client_left, client_top)
            dengluyouxi = WindowManager.find_template_in_window(hwnd, template_path, threshold)
            if dengluyouxi:
                print("找到图片", dengluyouxi[0], dengluyouxi[1], client_left, client_top)
                WindowManager.sleep(1)
                return True
            else:
                print("未找到", template_path)
                return False
        except Exception as e:
            print(f"发生错误: {str(e)}")

    @staticmethod
    def captureWindow(hwnd):
        """截取指定窗口句柄的图像并转为OpenCV格式"""
        # 获取窗口位置和尺寸
        left, top, right, bottom = win32gui.GetClientRect(hwnd)
        width = right - left
        height = bottom - top

        # 创建设备上下文和位图对象
        hwnd_dc = win32gui.GetWindowDC(hwnd)
        mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
        save_dc = mfc_dc.CreateCompatibleDC()
        bitmap = win32ui.CreateBitmap()
        bitmap.CreateCompatibleBitmap(mfc_dc, width, height)
        save_dc.SelectObject(bitmap)

        # 截取窗口内容
        save_dc.BitBlt((0, 0), (width, height), mfc_dc, (0, 0), win32con.SRCCOPY)

        # 转换为numpy数组并处理颜色通道
        img_data = bitmap.GetBitmapBits(True)
        img = np.frombuffer(img_data, dtype=np.uint8).reshape((height, width, 4))
        img = cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)  # 转换为BGR格式

        # 释放资源
        win32gui.DeleteObject(bitmap.GetHandle())
        save_dc.DeleteDC()
        mfc_dc.DeleteDC()
        win32gui.ReleaseDC(hwnd, hwnd_dc)
        return img

    @staticmethod
    def drag_window(hwnd, start_x, start_y, end_x, end_y):
        """
        在指定句柄的窗口中模拟按住左键拖动操作
        :param hwnd: 窗口句柄
        :param start_x: 拖动起始点相对于窗口左上角的 x 坐标
        :param start_y: 拖动起始点相对于窗口左上角的 y 坐标
        :param end_x: 拖动结束点相对于窗口左上角的 x 坐标
        :param end_y: 拖动结束点相对于窗口左上角的 y 坐标
            """
        random_num = random.randint(1, 10)
        # 按下左键
        win32api.SendMessage(hwnd, win32con.WM_LBUTTONDOWN, win32con.MK_LBUTTON, win32api.MAKELONG(start_x, start_y))
        # 移动鼠标
        for i in range(random_num):
            x = start_x + (end_x - start_x) * i // random_num
            y = start_y + (end_y - start_y) * i // random_num
            win32api.SendMessage(hwnd, win32con.WM_MOUSEMOVE, win32con.MK_LBUTTON, win32api.MAKELONG(x, y))
            WindowManager.sleep(1)
        # 释放左键
        win32api.SendMessage(hwnd, win32con.WM_LBUTTONUP, 0, win32api.MAKELONG(end_x, end_y))

    @staticmethod
    def drag_find(hwnd,img_path):
        start_x = 300
        start_y = 265
        end_x = 300
        end_y = 200
        while True:
            dengluyouxi = WindowManager.find_template_in_window(hwnd, img_path, 0.8)
            if dengluyouxi:
                WindowManager.click_in_window(hwnd, dengluyouxi[0] - 8 + 100, dengluyouxi[1] - 31 + 12)
                break
            else:
                WindowManager.drag_window(hwnd, start_x, start_y, end_x, end_y)
        print("找到图片", dengluyouxi[0] - 8, dengluyouxi[1] - 31)
